﻿using System;
using System.Collections.Generic;

namespace Gmantis.Controls.DataGrid
{
    public enum DataGridNewRowVisibility
    {
        Top,
        Bottom
    }

    public class DataGridNewRow : DataGridRow
    {
        // Fields
        private bool _isEnteringNewRow;

        // Events
        public event EventHandler<PropertyChangedEventArgs<bool>> IsEnteringNewRowChanged;

        public event EventHandler<PropertyChangedEventArgs<bool>> IsEnteringNewRowChanging;

        // Methods
        protected internal override void BindRowPresenter(DataGridRowPresenter presenter)
        {
            if (base.DataItem != null)
            {
                presenter.DataContext = base.DataItem;
            }
        }

        protected internal override DataGridRowHeaderPresenter CreateRowHeaderPresenter()
        {
            return new DataGridNewRowHeaderPresenter();
        }

        protected internal override DataGridRowPresenter CreateRowPresenter()
        {
            return new DataGridNewRowPresenter();
        }

        protected internal override object GetRowHeaderPresenterRecyclingKey()
        {
            return typeof(DataGridNewRowHeaderPresenter);
        }

        protected internal override object GetRowPresenterRecyclingKey()
        {
            return typeof(DataGridNewRowPresenter);
        }

        protected internal override bool HasCellPresenter(DataGridColumn column)
        {
            return this.IsEnteringNewRow;
        }

        protected internal override bool OnBeganRowEdit()
        {
            this.IsEnteringNewRow = true;
            return true;
        }

        protected internal override bool OnBeginningRowEdit()
        {
            base.DataItem = base.Model.DataConnection.CreateItem();
            DataGridBeginningNewRowEventArgs e = new DataGridBeginningNewRowEventArgs(this);
            base.Model.DataGrid.OnBeginningNewRow(e);
            if (!e.Cancel && (e.Item != null))
            {
                return true;
            }
            base.DataItem = null;
            return false;
        }

        protected internal override bool OnCanceledRowEdit()
        {
            this.IsEnteringNewRow = false;
            DataGridRowEventArgs e = new DataGridRowEventArgs(this);
            base.Model.DataGrid.OnCanceledNewRow(e);
            return true;
        }

        protected internal override bool OnCancelingRowEdit()
        {
            DataGridEndingNewRowEventArgs e = new DataGridEndingNewRowEventArgs(this);
            base.Model.DataGrid.OnCancelingNewRow(e);
            return !e.Cancel;
        }

        protected internal override bool OnCommitingRowEdit()
        {
            DataGridEndingNewRowEventArgs e = new DataGridEndingNewRowEventArgs(this);
            base.DataGrid.OnCommittingNewRow(e);
            return !e.Cancel;
        }

        protected internal override bool OnCommittedRowEdit()
        {
            KeyValuePair<int, object> pair = new KeyValuePair<int, object>((base.DataGrid.NewRowVisibility == DataGridNewRowVisibility.Top) ? 0 : base.Model.DataConnection.Count, base.DataItem);
            this.IsEnteringNewRow = false;
            KeyValuePair<int, object>[] addedItems = new KeyValuePair<int, object>[] { pair };
            base.Model.DataConnection.AddDataItems(addedItems);
            base.DataItem = null;
            base.DataGrid.OnCommittedNewRow(new DataGridRowEventArgs(this));
            return true;
        }

        private void OnIsEnteringNewRowChanged(bool newValue, bool oldValue)
        {
            if (this.IsEnteringNewRowChanged != null)
            {
                PropertyChangedEventArgs<bool> e = new PropertyChangedEventArgs<bool>
                {
                    NewValue = newValue,
                    OldValue = oldValue
                };
                this.IsEnteringNewRowChanged(this, e);
            }
        }

        private void OnIsEnteringNewRowChanging(bool newValue, bool oldValue)
        {
            if (this.IsEnteringNewRowChanging != null)
            {
                PropertyChangedEventArgs<bool> e = new PropertyChangedEventArgs<bool>
                {
                    NewValue = newValue,
                    OldValue = oldValue
                };
                this.IsEnteringNewRowChanging(this, e);
            }
        }

        protected internal override void OnLoaded()
        {
            base.OnLoaded();
            base.RowStyle = base.DataGrid.NewRowStyle;
            base.RowHeaderStyle = base.DataGrid.NewRowHeaderStyle;
        }

        protected internal override void UnbindRowPresenter(DataGridRowPresenter presenter)
        {
            presenter.DataContext = null;
        }

        // Properties
        public bool IsEnteringNewRow
        {
            get
            {
                return this._isEnteringNewRow;
            }
            internal set
            {
                bool oldValue = this._isEnteringNewRow;
                if (value != oldValue)
                {
                    this.OnIsEnteringNewRowChanging(value, oldValue);
                    this._isEnteringNewRow = value;
                    this.OnIsEnteringNewRowChanged(value, oldValue);
                }
            }
        }
    }
}
